import Style from 'ol/style/Style'
import Text from 'ol/style/Text'
import Icon from 'ol/style/Icon'
import MultiPoint from 'ol/geom/MultiPoint'
import * as turf from '@turf/turf'
import Fill from 'ol/style/Fill'
import Stroke from 'ol/style/Stroke'
import Point from 'ol/geom/Point'
import LineString from 'ol/geom/LineString'
import GeoJSON from 'ol/format/GeoJSON'
import { transform } from 'ol/proj'
import _ from 'lodash'

const redCircle = 'https://p1.qhimg.com/t01f5f31e7013363caf.png'
const highlightRedCircle = 'https://p2.qhimg.com/t01d9495ce3c4f1d149.png'
const slantLine = 'https://p3.qhimg.com/t0123ecbda3861f09af.png'

export function genStyleFunction(selfStyleFunc, calcStyleFuncs, vue) {
  return function (feature) {
    const isSelected = _.includes(
      vue.selectInteraction.getFeatures().array_.map((f) => f.getId()),
      feature.getId()
    )
    let styles = selfStyleFunc === null ? [] : selfStyleFunc(isSelected)
    calcStyleFuncs.forEach(
      (func) => (styles = styles.concat(func(feature, vue, isSelected)))
    )
    return styles
  }
}

export function stylePM(feature, vue, isSelected) {
  const textPt = new Point(
    turf.center(
      new GeoJSON().writeGeometryObject(feature.getGeometry())
    ).geometry.coordinates
  )
  if (!feature.get('connect').includes(vue.highlightPM)) {
    // downplay
    return [
      new Style({
        fill: new Fill({
          color: 'rgba(0, 0, 0, 0.2)',
        }),
        stroke: new Stroke({
          color: isSelected ? 'rgb(66, 173, 222)' : 'rgb(0, 0, 0)',
          width: isSelected ? 5 : 1,
        }),
      }),
      new Style({
        text: new Text({
          font: '12px Arial',
          text: feature.get('name'),
        }),
        geometry: textPt,
      }),
    ]
  } else {
    // highlight
    return [
      new Style({
        fill: new Fill({
          color: 'rgba(0, 0, 0, 0.2)',
        }),
        stroke: new Stroke({
          color: 'rgb(66, 173, 222)',
          width: 5,
        }),
      }),
      new Style({
        text: new Text({
          font: '12px Arial',
          text: feature.get('name'),
        }),
        geometry: textPt,
      }),
    ]
  }
}

export function pmBottomStyle(feature) {
  if (feature.get('bottom') === undefined) feature.set('bottom', [3, 2])
  const start = transform(
    feature.getGeometry().getCoordinates()[0][feature.get('bottom')[0]],
    'EPSG:3857',
    'EPSG:4326'
  )
  const end = transform(
    feature.getGeometry().getCoordinates()[0][feature.get('bottom')[1]],
    'EPSG:3857',
    'EPSG:4326'
  )
  const per_distance = 10 //cm
  const count =
    ((turf.distance(turf.point(start), turf.point(end)) * 1000).toFixed(2) *
      100) /
      per_distance -
    1
  const points = []

  for (let i = 0; i < count; i++) {
    points.push(
      transform(
        turf.destination(
          start,
          (per_distance / 100000) * i,
          turf.bearing(start, end)
        ).geometry.coordinates,
        'EPSG:4326',
        'EPSG:3857'
      )
    )
  }

  const rotation = Math.atan2(start[0] - end[0], start[1] - end[1])

  return [
    new Style({
      image: new Icon({
        anchor: [0.8, 0.1],
        rotation: rotation,
        scale: 0.1,
        src: slantLine,
      }),
      geometry: new MultiPoint(points),
    }),
  ]
}

export function kwStyle(feature, vue, isSelected) {
  const map = vue.map
  const kwType = feature.getId().split('-')[0]
  const blockType = feature.get('BlockType')
  const style = [
    new Style({
      fill: new Fill({
        color: 'rgba(0, 111, 0, 0.2)',
      }),
      stroke: new Stroke({
        color: isSelected ? 'rgb(66, 173, 222)' : 'rgb(0, 111, 0)',
        width: isSelected ? 5 : 1,
        lineDash: kwType.indexOf('Dash') > 0 ? [10] : null,
      }),
    }),
  ]
  if (blockType) {
    let background
    if (feature.getGeometry().getType() === 'Circle') {
      const pixel1 = map.getPixelFromCoordinate(
        feature.getGeometry().getCenter()
      )
      const extent = feature.getGeometry().getExtent()
      const coords2 = turf.toMercator(
        turf.midpoint(
          turf.toWgs84(turf.point([extent[0], extent[1]])),
          turf.toWgs84(turf.point([extent[2], extent[1]]))
        )
      ).geometry.coordinates
      const pixel2 = map.getPixelFromCoordinate(coords2)
      background = new Style({
        image: new Icon({
          src:
            blockType === 'fullBlock'
              ? '../../static/tuli/禁用.png'
              : '../../static/tuli/半圆.png',
          scale: (Math.abs(pixel1[1] - pixel2[1]) * 2) / 200,
        }),
        geometry: new Point(feature.getGeometry().getCenter()),
      })
    } else {
      const extent = feature.getGeometry().getExtent()
      const coords1 = turf.toMercator(
        turf.midpoint(
          turf.toWgs84(turf.point([extent[0], extent[1]])),
          turf.toWgs84(turf.point([extent[2], extent[3]]))
        )
      ).geometry.coordinates
      const coords2 = turf.toMercator(
        turf.midpoint(
          turf.toWgs84(turf.point([extent[0], extent[1]])),
          turf.toWgs84(turf.point([extent[2], extent[1]]))
        )
      ).geometry.coordinates
      const pixel1 = map.getPixelFromCoordinate(coords1)
      const pixel2 = map.getPixelFromCoordinate(coords2)
      background = new Style({
        image: new Icon({
          src:
            blockType === 'fullBlock'
              ? '../../static/tuli/叉.png'
              : '../../static/tuli/半正方形.png',
          scale: (Math.abs(pixel1[1] - pixel2[1]) * 2) / 200,
        }),
        geometry: new Point(coords1),
      })
    }
    style.push(background)
  }
  return style
}

export function dlStyle(feature, vue, isSelected) {
  const cableId = vue.highlightCable
  const dlType = feature.getId().split('-')[0]
  const ratio = 1 / Math.pow(vue.map.getView().getResolution(), 1 / 3)
  const intersectsPM = vue.pmLayer
    .getSource()
    .getFeatures()
    .filter((pm) =>
      pm
        .getGeometry()
        .intersectsCoordinate(feature.getGeometry().getCoordinates())
    )[0]
  const isMe =
    feature.get('dbid') === cableId &&
    intersectsPM !== undefined &&
    intersectsPM.get('connect').includes(vue.currentChannel)
  switch (dlType) {
    case 'DL400':
    case 'DL10k':
    case 'DL20k':
    case 'DL35k':
    case 'DL66k':
    case 'DL110k':
    case 'DL220k':
    case 'DL330k':
    case 'DL500k':
      let vol =
        dlType.indexOf('k') > 0
          ? parseInt(dlType.substring(2))
          : parseInt(dlType.substring(2)) / 1000
      return [
        new Style({
          image: new Icon({
            src: isSelected ? highlightRedCircle : redCircle,
            scale: isMe ? ratio / 30 : ratio / 70,
          }),
          text: new Text({
            font: ratio * 1.2 + 'px Arial Bold',
            text: vol + '',
          }),
        }),
      ]
    case 'TXDL':
      return [
        new Style({
          image: new Icon({
            src: isSelected
              ? '../../static/tuli/穿孔通讯_Selected.png'
              : '../../static/tuli/穿孔通讯.png',
            scale: isMe ? ratio / 3 : ratio / 6,
          }),
        }),
      ]
    case 'WZDL':
      return [
        new Style({
          image: new Icon({
            src: isSelected ? highlightRedCircle : redCircle,
            scale: isMe ? ratio / 30 : ratio / 70,
          }),
          text: new Text({
            font: ratio * 1.2 + 'px Arial Bold',
            text: '?',
          }),
        }),
      ]
    case 'DTDL':
      return [
        new Style({
          image: new Icon({
            src: isSelected ? highlightRedCircle : redCircle,
            scale: isMe ? ratio / 30 : ratio / 70,
          }),
        }),
      ]
    case 'CTDL':
      return [
        new Style({
          image: new Icon({
            src: isSelected ? highlightRedCircle : redCircle,
            scale: isMe ? ratio / 30 : ratio / 70,
          }),
          text: new Text({
            font: ratio * 1.2 + 'px Arial Bold',
            text: 'C',
          }),
        }),
      ]
    case 'HLX':
      return [
        new Style({
          image: new Icon({
            src: isSelected ? highlightRedCircle : redCircle,
            scale: isMe ? ratio / 30 : ratio / 70,
          }),
          text: new Text({
            font: ratio * 1.2 + 'px Arial Bold',
            text: '回',
          }),
        }),
      ]
  }
}

export function assistStyle(feature, vue, isSelected) {
  const assistType = feature.getId().split('-')[0]
  switch (assistType) {
    case 'ZHUJI': {
      if (
        isSelected &&
        vue.assistLayer
          .getSource()
          .getFeatures()
          [vue.assistLayer.getSource().getFeatures().length - 1].getId() !==
          feature.getId()
      ) {
        const clone = feature.clone()
        clone.setId(feature.getId())
        vue.assistLayer.getSource().removeFeature(feature)
        vue.assistLayer.getSource().addFeature(clone)
        feature = clone
      }
      let objName = feature.get('text')
      if (feature.get('connectDbid'))
        Object.values(vue.dlAllData).forEach((arr) => {
          const d = arr.filter((dl) => dl.id === feature.get('connectDbid'))
          if (d.length === 1) {
            objName = d[0].name
          }
        })
      if (objName === undefined) objName = ''
      const nonchs = objName.replace(/[\u4e00-\u9fa5]/g, '').length
      const textlen = objName.length - nonchs + nonchs / 2 + 1
      const ratio = 1 / Math.pow(vue.map.getView().getResolution(), 1 / 3)
      const font = ratio * 3
      const extent = vue.map.getView().calculateExtent(vue.map.getSize())
      const hpixels = vue.map.getView().getViewportSize_()[0]
      const coordsLen = feature.getGeometry().getCoordinates().length
      if (coordsLen < 2) {
        vue.assistLayer.getSource().removeFeature(feature)
        return
      }
      const textBearing = turf.bearing(
        turf.toWgs84(
          turf.point(feature.getGeometry().getCoordinates()[coordsLen - 2])
        ),
        turf.toWgs84(
          turf.point(feature.getGeometry().getCoordinates()[coordsLen - 1])
        )
      )
      const fontRatio =
        ((turf.bearingToAzimuth(textBearing) >= 180
          ? Math.abs(turf.bearingToAzimuth(textBearing) - 270)
          : Math.abs(turf.bearingToAzimuth(textBearing) - 90)) /
          90) *
          0.25 +
        1
      const underline =
        (turf.distance(
          turf.toWgs84(turf.point([extent[0], extent[1]])),
          turf.toWgs84(turf.point([extent[2], extent[1]]))
        ) /
          hpixels) *
        font *
        textlen *
        fontRatio
      const geom = new LineString([
        feature.getGeometry().getCoordinates()[coordsLen - 1],
        turf.toMercator(
          turf.destination(
            turf.toWgs84(
              turf.point(feature.getGeometry().getCoordinates()[coordsLen - 1])
            ),
            underline,
            textBearing
          )
        ).geometry.coordinates,
      ])

      return [
        new Style({
          text: new Text({
            font: font + 'px Arial',
            text: objName,
            overflow: true,
            placement: 'line',
            textAlign: 'end',
            textBaseline: 'bottom',
            fill: new Fill({
              color: isSelected ? 'rgb(200, 100, 100)' : 'rgb(0,0,0)',
            }),
          }),
          stroke: new Stroke({
            color: isSelected ? 'rgb(66, 173, 222)' : 'rgb(0,0,0)',
            width: isSelected ? 2.5 : 1.5,
          }),
          geometry: geom,
        }),
        new Style({
          stroke: new Stroke({
            color: isSelected ? 'rgb(66, 173, 222)' : 'rgb(0,0,0)',
            width: isSelected ? 2.5 : 1.5,
          }),
        }),
      ]
    }
    case 'JLX': {
      const ratio = 1 / Math.pow(vue.map.getView().getResolution(), 1 / 3)
      const font = ratio * 2

      const geometry = feature
        .getGeometry()
        .clone()
        .transform('EPSG:3857', 'EPSG:4326')
      const styles = [
        new Style({
          text: new Text({
            font: font + 'px Arial',
            text:
              (
                turf.length(new GeoJSON().writeGeometryObject(geometry)) *
                1000000
              ).toFixed(0) + 'mm',
          }),
        }),
        new Style({
          stroke: new Stroke({
            color: isSelected ? 'rgb(66, 173, 222)' : 'rgb(0,150,0)',
            width: 2,
            lineDash: [10],
          }),
        }),
      ]
      geometry.forEachSegment(function (start, end) {
        const rotation = Math.atan2(end[1] - start[1], end[0] - start[0])
        const rotation2 = Math.atan2(start[1] - end[1], start[0] - end[0])
        // arrows
        styles.push(
          new Style({
            geometry: new Point(end).transform('EPSG:4326', 'EPSG:3857'),
            image: new Icon({
              src: '../../static/tuli/arrow.png',
              anchor: [0.75, 0.5],
              rotateWithView: true,
              rotation: -rotation,
            }),
          })
        )
        styles.push(
          new Style({
            geometry: new Point(start).transform('EPSG:4326', 'EPSG:3857'),
            image: new Icon({
              src: '../../static/tuli/arrow.png',
              anchor: [0.75, 0.5],
              rotateWithView: true,
              rotation: -rotation2,
            }),
          })
        )
      })

      return styles
    }
  }
}

function getCircleCanvas(color = '#e9e9e9') {
  const canvas = document.createElement('canvas')
  canvas.width = 200
  canvas.height = 200
  var ctx = canvas.getContext('2d')

  /*开始圆环*/
  var circleObj = {
    ctx: ctx,
    /*圆心*/
    x: 100,
    y: 100,
    /*半径*/
    radius: 95,
    /*环的宽度*/
    lineWidth: 10,
  }
  circleObj.startAngle = 0
  circleObj.endAngle = Math.PI * 2
  circleObj.color = color

  ctx.beginPath()
  ctx.arc(
    circleObj.x,
    circleObj.y,
    circleObj.radius,
    circleObj.startAngle,
    circleObj.endAngle,
    false
  )
  //设定曲线粗细度
  ctx.lineWidth = circleObj.lineWidth
  //给曲线着色
  ctx.strokeStyle = circleObj.color
  //连接处样式
  ctx.lineCap = 'round'
  //给环着色
  ctx.stroke()
  ctx.closePath()

  return canvas
}

function getSlantLine() {
  const canvas = document.createElement('canvas')
  canvas.width = 200
  canvas.height = 200
  var ctx = canvas.getContext('2d')
  ctx.lineWidth = 10
  ctx.strokeStyle = '#dddddd'
  ctx.beginPath()
  ctx.moveTo(0, 0)
  ctx.lineTo(200, 200)
  ctx.stroke()
  ctx.closePath()
  return canvas
}

// WEBPACK FOOTER //
// ./src/components/pmEditor/style.js
